package org.kl.bf.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.TaskQuery;
import org.kl.bf.entity.basic.Role;
import org.kl.bf.entity.basic.User;
import org.kl.bf.repository.basic.RoleDao;
import org.kl.bf.service.basic.UserService;
import org.kl.bf.web.base.BasicController;
import org.kl.bpm.entity.conf.BpmConfUser;
import org.kl.bpm.entity.conf.BpmKvRecord;
import org.kl.bpm.entity.conf.BpmProcess;
import org.kl.bpm.operation.SaveDraftOperation;
import org.kl.bpm.repository.conf.BpmConfUserDao;
import org.kl.bpm.service.conf.BpmKvRecordService;
import org.kl.bpm.service.conf.BpmProcessService;
import org.kl.bpm.utils.BpmConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 工作流Service父类
 * 
 * @author QJ
 * @date 2014年10月9日
 */
@Component
public class BasicBpmService {
	@Autowired
	protected BpmConfUserDao bpmConfUserDao;
	@Autowired
	protected UserService userService;
	@Autowired
	protected RoleDao roleDao;
	@Autowired
	protected RuntimeService runtimeService;
	@Autowired
	protected IdentityService identityService;
	@Autowired
	protected BpmProcessService bpmProcessService;
	@Autowired
	protected BpmKvRecordService bpmKvRecordService;
	@Autowired
	protected TaskService taskService;

	/**
	 * 检查流程配置
	 * 
	 * @param bpmProcess
	 * @param variables
	 * @param businessKey
	 */
	private void checkBpmConf(BpmProcess bpmProcess, Map<String, Object> variables, String businessKey) {
		List<BpmConfUser> confUsers = bpmConfUserDao.findByBpmConfNodeBpmConfBaseId(bpmProcess.getBpmConfBase().getId());
		List<String> allowExpression = new ArrayList<String>();
		allowExpression.add("${" + BpmConstants.INITIATOR + "}");
		allowExpression.add("${" + BpmConstants.NEXT_ASSIGNEE + "}");
		for (BpmConfUser confUser : confUsers) {
			// 负责人
			if (confUser.getType() == 0) {// 负责人
				User u = userService.getUser(confUser.getValue());
				if (u == null) {
					throw new ServiceException("审批流程节点中存在无效的审批用户，请检查配置!");
				}
			} else if (confUser.getType() == 1) {// 常用关系
				if (!allowExpression.contains(confUser.getValue())) {
					throw new ServiceException("无法解析表达式:" + confUser.getValue() + ",请检查程序");
				}
			} else if (confUser.getType() == 2) {// 角色
				Role role = roleDao.findByRoleNo(confUser.getValue());
				if (role == null) {
					throw new ServiceException("审批流程节点中存在无效角色,请联系管理员检查配置");
				}
				List<String> users;
				users = userService.getUsersIdByRoleNo(confUser.getValue());
				if (users.size() == 0) {
					throw new ServiceException("审批流程节点中存在角色<" + role.getRoleName() + ">没有配置人员，请联系项目管理员进行分配");
				} else if (users.size() > 1) {
					throw new ServiceException("审批流程节点中存在角色<" + role.getRoleName() + ">审批人数过多(" + users.size() + ")，请联系项目管理员进行调整");
				}
			} else if (confUser.getType() == 3) {// 直属领导
				// 直属上级暂不检查
			} else if (confUser.getType() == 4) {// EL表达式
				Object o = variables.get(confUser.getValue().replace("${", "").replace("}", ""));
				if (o == null && !allowExpression.contains(confUser.getValue())) {
					throw new ServiceException("无法解析表达式:" + confUser.getValue() + ",请通知管理员检查程序");
				}
			}
		}
	}

	/**
	 * 默认启动流程工作
	 * 
	 * @param bpmProcess
	 * @param variables
	 * @param businessKey
	 * @return
	 */
	public ProcessInstance defaultProcess(BpmProcess bpmProcess, Map<String, Object> variables, String businessKey) {
		// 检查流程配置
		checkBpmConf(bpmProcess, variables, businessKey);
		// 用来设置启动流程的人员ID，引擎会自动把用户ID保存到activiti:initiator中
		ProcessInstance processInstance = null;
		identityService.setAuthenticatedUserId(BasicController.getCurrentUserId());
		processInstance = runtimeService.startProcessInstanceById(bpmProcess.getBpmConfBase().getProcessDefinitionId(), businessKey,
				variables);
		BpmKvRecord bpmKvRecord = new BpmKvRecord();
		bpmKvRecord.setCategory(bpmProcess.getId());
		bpmKvRecord.setStatus(SaveDraftOperation.STATUS_RUNNING);
		bpmKvRecord.setRef(processInstance.getId());
		bpmKvRecord.setBusinessId(businessKey);
		bpmKvRecord.setProcessCreate(BasicController.getCurrentUserName());
		bpmKvRecord.setProcessTime(new Date());
		bpmKvRecordService.saveBpmKvRecord(bpmKvRecord);
		return processInstance;
	}

	/**
	 * 默认的取消流程
	 * 
	 * @param bpmProcess
	 * @param variables
	 * @param businessKey
	 * @return
	 */
	public void defaultCancel(DelegateExecution execution, String authenticatedUserId) {
		// 预留，方便今后统一调整,此处可写入取消审批时的统一动作，如删除相关审批信息
	}

	/**
	 * 获取某个流程当前任务
	 * 
	 * @param processInstanceId
	 * @param processInstanceBusinessKey
	 * @return
	 */
	public String getCurrentTask(String processInstanceId, String processInstanceBusinessKey) {
		TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(BasicController.getCurrentUserId()).active();
		taskQuery.processInstanceId(processInstanceId).processInstanceBusinessKey(processInstanceBusinessKey);
		return taskQuery.list().get(0).getId();
	}
}
